import subprocess
import re
from lxml import etree as ElementTree

class cmmlParser(object):

    def __init__(self):
        self.cmmlfilename = ""  
        self.Etree = ""
        return

    def setcmmlfilename(self, filename):
        """ parses a cmml file and sets up the basic tree

        """
        self.cmmlfilename = filename
        self.Etree = ElementTree
        self.doc = self.Etree.parse(self.cmmlfilename)
        self.root = self.doc.getroot()
        return

#    def runcommand(self, cmd):
#        runit = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#        out, err = runit.communicate()
#        print out + err


    def edithead(self, headid, text):
        """ Edits the head title information

        """
        head = self.root.getiterator('head')
        for h in head:
            t = h.find('title')
            t.text = text

        self.doc.write(self.cmmlfilename)
        return

    def addmetaid(self, id):
        """ Adds a meta tag to the head that matches the itemid
            in the database
        """
        head = self.root.getiterator('head')
        
        for h in head:
            mymeta = self.Etree.SubElement(h, 'meta')
            mymeta.set('name', "dbid")
            mymeta.set('content', str(id))
        
        self.doc.write(self.cmmlfilename)
        return
    
    def addmetaitem(self, metadict):
        """ Given a dictionary of meta info, adds a meta element to
            the head of the cmmlfile
        """
        head = self.root.getiterator('head')
        
        for h in head:
            mymeta = self.Etree.SubElement(h, 'meta')
            mymeta.set('name', metadict['name'])
            mymeta.set('content', metadict['content'])
        
        self.doc.write(self.cmmlfilename)
        return

    def updatesourcetag(self, sourcename):
        """ Updates the source file location in the cmml file

        """
        stream = self.root.getiterator('stream')
        for s in stream:
            i = s.find('import')
            i.set('src', sourcename)

        self.doc.write(self.cmmlfilename)
        return

    def gettitle(self):
        """ Returns the title (from the head) of the cmml file

        """
        root = self.doc.getroot()
        head = root.getiterator('head')
        for h in head:
            t = h.find('title')
            title = t.text

        # Work around a bug in my marking up app - makimap.py, which added
        # newlines and tabs to the title in the head
        title = re.sub(r'\n', r'', str(title))
        title = re.sub(r'\t', r'', title)

        return title

    def getclipsfromcmml(self):
        """ returns a dictionary of clips from the object's cmmlfile

        """
        clips = self.root.getiterator('clip')
        cliplist = []
        for clip in clips:
            clipdict = {}
            clipdict['id'] = clip.get('id')    
            clipdict['starttime'] = clip.get('start')    
            clipdict['endtime'] = clip.get('end')    
            desc = clip.find('desc')
            clipdict['desc'] = desc.text
            clipdict['a_href'] = None  # FIXME
            clipdict['a_text'] = None  # FIXME
            clipdict['img_src'] = None # FIXME

            cliplist.append(clipdict)

        return cliplist

    def getheadinfofromcmml(self):
        """ given a cmmlfile, returns a list of the meta tags in the head

        """
        head = self.root.getiterator('head')
        metalist = []
        for h in head:
            mlist = h.findall('meta')
            for m in mlist:
                metadict = {}
                metadict['name'] = m.get('name')
                metadict['content'] = m.get('content')
                metadict['id'] = None 
                metadict['scheme'] = None
                metalist.append(metadict)

        return metalist

    def addclipstocmmlfile(self, cliplist):
        """ Given a list of dictionary objects representing clips, removes
            the old list of clips from the cmml file, then writes a new list.
            Note that the cliplist is assumed to be in temporal order
        """
        root = self.doc.getroot()
        # First, we get rid of the old list of clips from the cmml
        clips = root.getiterator('clip')
        for c in clips:
            root.remove(c)

       # Now we write the new clips back
        for clip in cliplist:
            newclip = self.Etree.SubElement(root, 'clip')
            newclip.set('start', str(clip['start_time']))
            if (clip['end_time']):
                newclip.set('end', str(clip['end_time']))
            newclip.set('id', str(clip['id']))
            img = self.Etree.SubElement(newclip, 'img')
            img.set('src', str(clip['img_src']))
            desc = self.Etree.SubElement(newclip, 'desc')
            desc.text = clip['desc']
        
        self.doc.write(self.cmmlfilename)
        return

    def syncheadmetas(self, metalist):
        """ Takes a list of head meta tags and writes them to the cmml file

            Returns nothing - that's probably a _bad thing_
        """
        root = self.doc.getroot()
        head = root.getiterator('head')
        for h in head:
            mlist = h.findall('meta')
            for m in mlist:
                h.remove(m)

        # Now write the meta tags back 
        head = root.getiterator('head')
        for h in head:
            for meta in metalist:
                newmeta = self.Etree.SubElement(h, 'meta')
                newmeta.set('id', str(meta.id))
                newmeta.set('name', meta.name)
                newmeta.set('content', meta.content)

        self.doc.write(self.cmmlfilename)
        return

    def editmeta(self, metaid, field, text):
        """ Edits a meta tag, given the field (name or content) and the
            text for that element
        """
        root = self.doc.getroot()
        head = root.getiterator('head')
        for h in head:
            mlist = h.findall('meta')
            for m in mlist:
                if m.get('id') == metaid:
                    m.set(field, text)

        self.doc.write(self.cmmlfilename)
        return

    def createnewfile(self, sourcefilename, oggsourcename):
        """ Creates a new cmmlfile from scratch, given just source file
            information
        """
        Etree = ElementTree
        root = Etree.Element('cmml')
        stream = Etree.SubElement(root, 'stream')
        stream.set('timebase', 'npt:0')
        importtag = Etree.SubElement(stream, 'import')
        importtag.set('src', oggsourcename)
        head = Etree.SubElement(root, 'head')
        title = Etree.SubElement(head, 'title')
        tree = Etree.ElementTree(root)
        tree.write(sourcefilename)

        return

#    def __getelementiterator(self, element):
#        Etree = ElementTree
#        doc = Etree.parse(self.cmmlfilename)
#        root = doc.getroot()
#        
#        elementiterator = root.getiterator(element)
#        return

#    def addheadmetas(metalist):
#        root = self.doc.getroot()
#        head = root.getiterator('head')
#        for h in head:
#            mlist = h.findall('meta')
#            for m in mlist:
#                h.remove(m)



